import React, { useState } from 'react';
import { NetworkStatus } from '@apollo/client';
import {
  Box,
  CartMiniSummary,
  Grid,
  GridItem,
  Icon,
  LoadingPlaceholder,
  makeToast,
  MultiselectOffer,
  Text,
} from '@nova-hf/ui';
import { ErrorBanner } from 'beta/components/error/ErrorBanner';
import { FormWrapper } from 'beta/containers/layout/FormWrapper';
import StepWrapper from 'beta/containers/layout/StepWrapper';
import UI from 'beta/store/ui';
import { IContext } from 'beta/typings/context';
import { inject, observer } from 'mobx-react';
import { useRouter } from 'next/router';
import {
  ContractItemType,
  ContractStatus,
  EquipmentRentalStatus,
  useAvailableOptionsLazyQuery,
  useContractsQuery,
  useSendDeviceItemsToNavMutation,
  useServiceQuery,
  Variant,
  VariantProductType,
} from 'typings/graphql';
import { useTranslation } from 'utils/i18n';

import { ROUTER_25X_VAIANT_ID } from '../../containers/FiberServiceContainer';

import { SelectStore } from './components/SelectStore';

const ROUTER_VARIANT_ID = 'fiber-router';
const KASTARI_VARIANT_ID = 'kastari';

type BunadarleigaProps = {
  customerId: string;
  serviceId: string;
  ui?: UI;
};

const Bunadarleiga = ({ customerId, serviceId, ui }: BunadarleigaProps) => {
  const { t } = useTranslation(['fiber', 'errors']);
  const router = useRouter();
  const [selectedItems, setSelectedItems] = useState<Record<
    string,
    { variant: Variant; quantity: number }
  > | null>(null);
  const [numOfRouterAlreadyOnContract, setNumOfRouterAlreadyInContract] = useState(0);
  const [numOfKastariAlreadyOnContract, setNumOfKastariAlreadyInContract] = useState(0);
  const [contractId, setContractId] = useState('');
  const [storeId, setStoreId] = useState('');

  const {
    data: serviceData,
    error,
    loading,
  } = useServiceQuery({
    variables: {
      serviceId,
    },
    skip: !serviceId,
  });

  const {
    loading: contractLoading,
    error: contractError,
    refetch,
    networkStatus,
  } = useContractsQuery({
    variables: {
      input: {
        serviceId,
        customerId,
      },
    },
    onCompleted(data) {
      if (data.contracts.contracts.length) {
        const activeOrPendingContractId = data.contracts.contracts.find(
          (contract) =>
            contract.status === ContractStatus.Active || contract.status === ContractStatus.Pending,
        )?.id;
        if (activeOrPendingContractId) {
          setContractId(activeOrPendingContractId);
          availableOptions({
            variables: {
              input: {
                id: activeOrPendingContractId,
                productType: VariantProductType.HardGood,
              },
            },
          });
          const contract = data.contracts.contracts.find(
            (contract) => contract.id === activeOrPendingContractId,
          );
          const devices = contract?.contractItems.filter(
            (item) =>
              item.type === ContractItemType.Device &&
              (item.status === EquipmentRentalStatus.Active ||
                item.status === EquipmentRentalStatus.Pending),
          );
          const kastariAmount = devices?.filter(
            (device) => device.variantId === KASTARI_VARIANT_ID,
          );
          const routerAmount = devices?.filter(
            (device) =>
              device.variantId === ROUTER_VARIANT_ID || device.variantId === ROUTER_25X_VAIANT_ID,
          );
          setNumOfRouterAlreadyInContract(routerAmount?.length ?? 0);
          setNumOfKastariAlreadyInContract(kastariAmount?.length ?? 0);
        }
      }
    },
    skip: !serviceId || !customerId,
  });

  const [availableOptions, { data: availableOptionsData, error: optionsError }] =
    useAvailableOptionsLazyQuery({
      onCompleted(data) {
        if (data?.availableOptions?.length) {
          data.availableOptions.forEach((option) => {
            if (option?.variants) {
              option.variants.forEach((variant) => {
                if (variant?.id && variant.__typename === 'Variant') {
                  setSelectedItems((prevSelectedItems) => ({
                    ...prevSelectedItems,
                    [variant.id]: { variant: variant as Variant, quantity: 0 },
                  }));
                }
              });
            }
          });
        }
      },
    });

  const [sendToNav, { loading: sendToNavLoading }] = useSendDeviceItemsToNavMutation({
    onCompleted(data) {
      if (data?.sendDeviceItemsToNav?.id) {
        makeToast.success(t('fiberDevices.sendSuccess'), '');
        router.push(`/beta/${customerId}/thjonustur/${serviceId}`);
      }
    },
    onError(error) {
      if (error) {
        makeToast.danger(t('fiberDevices.sendFailure'), error.message);
      }
    },
  });

  const onSubmit = () => {
    if (selectedItems && storeId) {
      const selectedDevices = Object.entries(selectedItems).map(([id, { quantity }]) => ({
        variantId: id,
        amount: quantity,
      }));
      sendToNav({
        variables: {
          input: {
            contractId,
            navisionStoreId: storeId,
            deliveredDevices: selectedDevices,
          },
        },
      });
    }
  };

  const handleIncreaseOrDecrease = (variantId: string, quantity: number) => {
    if (selectedItems && selectedItems[variantId]) {
      setSelectedItems((prevSelectedItems) => {
        const currentItem = selectedItems[variantId];
        return {
          ...prevSelectedItems,
          [variantId]: {
            variant: currentItem.variant,
            quantity: quantity,
          },
        };
      });
    } else {
      const foundVariant =
        (availableOptionsData?.availableOptions
          ?.flatMap((option) => option?.variants ?? [])
          .find(
            (variant) => variant?.__typename === 'Variant' && variant?.id === variantId,
          ) as Variant) ?? null;
      if (foundVariant) {
        setSelectedItems((prevSelectedItems) => {
          return {
            ...prevSelectedItems,
            [variantId]: { variant: foundVariant, quantity: quantity },
          };
        });
      }
    }
  };

  const hasRentalProduct = numOfKastariAlreadyOnContract > 0 || numOfRouterAlreadyOnContract > 0;
  const routerTranslateText =
    numOfRouterAlreadyOnContract === 1
      ? t('fiberItems.rentalSignup.routerSingular')
      : t('fiberItems.rentalSignup.routerPlural');
  const kastariTranslateText =
    numOfKastariAlreadyOnContract === 1
      ? t('fiberItems.rentalSignup.kastariSingular')
      : t('fiberItems.rentalSignup.kastariPlural');

  const errorOrLoading = error || contractError || loading || contractLoading || optionsError;

  const totalPrice = selectedItems
    ? Object.values(selectedItems).reduce((total, { variant, quantity }) => {
        return total + (variant.monthlyCharge || 0) * quantity;
      }, 0)
    : 0;

  return (
    <StepWrapper
      color={ui?.serviceColor}
      returnUrl={`/beta/${customerId}/thjonustur/${serviceId}`}
      title={t('fiberItems.rentalSignup.sideMenuTitle')}
      subTitle={serviceData?.service?.name ?? ''}
      icon="novaLogo"
      childrenBottom={
        <CartMiniSummary
          color="white"
          cartPayNowItems={
            selectedItems
              ? Object.entries(selectedItems)
                  .map(([, { variant, quantity }]) => ({
                    title: variant.name,
                    price: (variant?.monthlyCharge ?? 0) * quantity,
                  }))
                  .filter((item) => item.price !== 0)
              : [{ price: 0, title: t('fiberItems.rentalSignup.noProductTitle') }]
          }
          payNow={{
            price: totalPrice,
            title: t('fiberItems.rentalSignup.totalPriceLabel'),
          }}
          cartTitle={t('fiberItems.activeDevices')}
        />
      }
    >
      <FormWrapper
        color={ui?.serviceColor}
        isDisabled={!!errorOrLoading || !storeId}
        isLoading={sendToNavLoading}
        isCurrentStep
      >
        <SelectStore
          onSelectStore={setStoreId}
          storeSelected={storeId}
          color={ui?.serviceColor}
          contractId={contractId}
        />
      </FormWrapper>
      <FormWrapper
        color={ui?.serviceColor}
        isDisabled={!!errorOrLoading || !totalPrice}
        isLoading={sendToNavLoading}
        isCurrentStep
        isLastStep
        hasBackButton
        customButtonTitle={t('fiberItems.rentalSignup.confirmButton')}
        onClick={onSubmit}
      >
        {errorOrLoading ? (
          <ErrorBanner
            eyebrowTexts={[
              t('errors:rentalSignup.eyebrows.1'),
              t('errors:rentalSignup.eyebrows.2'),
              t('errors:rentalSignup.eyebrows.3'),
            ]}
            titles={[
              t('errors:rentalSignup.titles.1'),
              t('errors:rentalSignup.titles.2'),
              t('errors:rentalSignup.titles.3'),
            ]}
            descriptions={
              error || contractError
                ? [
                    t('errors:rentalSignup.generalDescriptions.1'),
                    t('errors:rentalSignup.generalDescriptions.2'),
                    t('errors:rentalSignup.generalDescriptions.3'),
                  ]
                : [
                    t('errors:rentalSignup.applicableVariantsDescriptions.1'),
                    t('errors:rentalSignup.applicableVariantsDescriptions.2'),
                    t('errors:rentalSignup.applicableVariantsDescriptions.3'),
                  ]
            }
            icon="zap"
            color="attention"
            showLoading={loading || contractLoading || networkStatus === NetworkStatus.refetch}
            refetchButton={{
              text: t('errors:buttons.refresh'),
              icon: 'refresh',
              onClick: () => refetch(),
            }}
            loadingComponent={
              <>
                <LoadingPlaceholder width="100%" height={8} pace="slow" />
                <Box display="flex" flexDirection="row" gap={5} marginTop={4}>
                  <LoadingPlaceholder height={50} width="6/12" pace="slow" />
                  <LoadingPlaceholder height={50} width="6/12" pace="slow" />
                </Box>
              </>
            }
          />
        ) : (
          <>
            <Box display="flex" flexDirection="column" justifyContent="center" marginBottom={3}>
              <Text variant="h5" color="black100">
                {t('fiberItems.rentalSignup.title')}
              </Text>
            </Box>

            {hasRentalProduct && (
              <Box display="flex" flexDirection="column" gap={0} marginBottom={4}>
                {numOfRouterAlreadyOnContract > 0 && (
                  <Box display="inline-flex" gap={1} alignItems="center">
                    <Icon icon="kastari" color={ui?.serviceColor} size={16} />{' '}
                    <Text variant="pSmallRegular" color={ui?.serviceColor}>
                      {t('fiberItems.rentalSignup.customerHasDevice', {
                        numDevices: numOfRouterAlreadyOnContract,
                        deviceName: routerTranslateText,
                      })}
                    </Text>
                  </Box>
                )}
                {numOfKastariAlreadyOnContract > 0 && (
                  <Box display="inline-flex" gap={1} alignItems="center">
                    <Icon icon="router" color={ui?.serviceColor} size={16} />{' '}
                    <Text variant="pSmallRegular" color={ui?.serviceColor}>
                      {t('fiberItems.rentalSignup.customerHasDevice', {
                        numDevices: numOfKastariAlreadyOnContract,
                        deviceName: kastariTranslateText,
                      })}
                    </Text>
                  </Box>
                )}
              </Box>
            )}
            <Grid gridTemplate={{ sm: 1, xl: 2 }}>
              {availableOptionsData?.availableOptions?.map((item) => {
                return item?.variants?.map((variant) => {
                  if (!variant?.id) return null;
                  const currentQuantiy = selectedItems
                    ? selectedItems[variant.id]?.quantity ?? 0
                    : 0;
                  return (
                    <GridItem key={variant.id} gridColumn={{ sm: 'span1' }}>
                      <MultiselectOffer
                        active
                        color={ui?.serviceColor}
                        incrementDecrementButton={{
                          allowDecrement: true,
                          allowIncrement: true,
                          color: ui?.serviceColor,
                          currentValue: currentQuantiy,
                          onDecrement: () =>
                            handleIncreaseOrDecrease(
                              variant.id,
                              currentQuantiy - 1 > 0 ? currentQuantiy - 1 : 0,
                            ),
                          onIncrement: () =>
                            handleIncreaseOrDecrease(variant.id, currentQuantiy + 1),
                        }}
                        product={{
                          description: variant?.description ?? '',
                          id: 'black',
                          image: {
                            alt: variant.name,
                            src: variant.imageUrl ?? '',
                          },
                          name: variant.productName ?? variant.name ?? '',
                          price: {
                            amount: variant?.monthlyCharge ?? 0,
                            unit: t('fiberItems.rentalSignup.monthlyUnit'),
                          },
                          vendor: '',
                        }}
                      />
                    </GridItem>
                  );
                });
              })}
            </Grid>
          </>
        )}
      </FormWrapper>
    </StepWrapper>
  );
};

Bunadarleiga.getInitialProps = ({ pathname, query }: IContext) => {
  return {
    pathname,
    customerId: query.customerId,
    serviceId: query.serviceId,
    namespacesRequired: ['fiber', 'errors', 'steps'],
  };
};

export default inject('steps', 'ui')(observer(Bunadarleiga));
